using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Runtime.InteropServices;

using QTOControlLib;
using QTOLibrary;
using ImageFileOverlay;
using ImageIngestion;




namespace AssetCapture
{
    public class VideoIngestion : System.Windows.Forms.Form
    {
        private AxQTOControlLib.AxQTControl axQTControl1;
        public delegate void disPlayDelegate(string message);
        public delegate void disPlayProgess(int percentage);
        public delegate void updateFrame(int totalFrame, bool doubleFrame);

        //Take the 'x,y' as the resize dimension ; 'fileSeqPathName' for the orignal frame to be resized and to be create the movie
        //'targetPathName' for the final movie location, 'alpha' stands for the transparent % you want for the overlayImage.
        public void ExtractImage(int x, int y, string MoviePathName, string targetPathName, string overlayPic ,int alpha, disPlayDelegate trace)
		{
			string errMsg = "";
            ImageOverLay overlayOb = new ImageOverLay();

            //Initialize the Control 
            //initialize(MoviePathName);
            //Resize the Controler with Resize parameter + the offset adjustment for the quickTime.
            axQTControl1.Sizing = QTSizingModeEnum.qtMovieFitsControl;
            axQTControl1.Size = new System.Drawing.Size(x+2, y+18);

            try
            {
                QTMovie theMovie = axQTControl1.Movie;
                Image overLay = Image.FromFile(overlayPic);

                //Get the proper rate of capturing movie frame
                float tRate = (float)600/theMovie.StaticFrameRate;
                string digitNumber = theMovie.EndTime.ToString();
                int number = digitNumber.Length;
                string digitN;
                string suffix;
                int nu;
                for (float i = 0; i < theMovie.EndTime; i=i+tRate)
                {
                    //Get the frame at specific time 
                    theMovie.CopyFrame(i);

                    Image oImage = Clipboard.GetImage();
                    if (oImage != null)
                    {
                        //Call overlayImage function to apply overlay image
                        //oImage = overlayOb.OverlayImage(oImage, overLay, alpha);
                        //Start suffix adding for file name
                        suffix = "";
                        digitN = i.ToString();
                        nu = digitN.Length;
                        //Get the suffix for naming
                        for (int j = 0; j < (number - nu); j++)
                            suffix = suffix + '0';
                        oImage.Save(targetPathName + "\\" + suffix+ i + ".jpg", ImageFormat.Jpeg);
                        oImage.Dispose();
                    }
                    Clipboard.Clear();
                    
                }
                axQTControl1.Dispose();

            }
            catch (COMException ex)
            {
                // catch COM exceptions from QT control
                errMsg = "Unable To Load the Movie , Please Check if it is QuickTime Playable Video \n\n" + ex.ErrorCode.ToString("X") + "\n";
                QTUtils qtu = new QTUtils();
                errMsg += "QT Error code : " + qtu.QTErrorFromErrorCode(ex.ErrorCode).ToString();
                trace(errMsg);
            }
            catch (Exception ex)
            {
                // catch any exception
                errMsg = "Unable To Load the Video , Please Check if it is QuickTime Playable Video \n\n" + ex.ToString();
                trace(errMsg);
            }
            
			if (errMsg != "")
			{
				string msg = "Unable to create movie:\n\n";
				msg += errMsg;
                trace(msg);
			}

		}

        // No Overlay Image applied 
        // Split the picture based on the required number of slice
        // Call back function to show the progress
        public void ExtractImage(int x, int y, string MoviePathName, string targetPathName, int totalSlice, int sliceIndex, disPlayDelegate trace, disPlayProgess showProgress)
        {
            string errMsg = "";
            ImageOverLay overlayOb = new ImageOverLay();
            ImageIngestion.ImageIngestion imageIngestOb = new ImageIngestion.ImageIngestion();

            //Initialize the Control with Resize parameter + the offset adjustment for the quickTime.
            //initialize(MoviePathName);
            //Resize the Controler 
            axQTControl1.Sizing = QTSizingModeEnum.qtControlFitsMovie;

            try
            {
                QTMovie theMovie = axQTControl1.Movie;

                //Get the proper rate of capturing movie frame
                float tRate = (float)600 / theMovie.StaticFrameRate;
                string digitNumber = theMovie.EndTime.ToString();
                int number = digitNumber.Length;
                string digitN;
                string suffix;
                int nu;
                int endTime = theMovie.EndTime;

                for (float i = 0; i < endTime; i = i + tRate)
                {
                    //Get the frame at specific time 
                    theMovie.CopyFrame(i);

                    Image oImage = Clipboard.GetImage();
                    if (oImage != null)
                    {
                        //Ingested the required Image
                        oImage = imageIngestOb.DivideImage(totalSlice, sliceIndex, oImage, x, y);

                        //Start suffix adding for file name
                        suffix = "";
                        digitN = i.ToString();
                        nu = digitN.Length;
                        //Get the suffix for naming
                        for (int j = 0; j < (number - nu); j++)
                            suffix = suffix + '0';
                        oImage.Save(targetPathName + "\\" + suffix + i + ".jpg", ImageFormat.Jpeg);
                        oImage.Dispose();
                        //Call the CallBack fucntion to update the Progress of the Extraction
                        showProgress(Convert.ToInt32(i / endTime * 100));
                    }
                    Clipboard.Clear();

                }
                axQTControl1.Dispose();

            }
            catch (COMException ex)
            {
                // catch COM exceptions from QT control
                errMsg = "Unable To Load the Video , Please Check if it is QuickTime Playable Video \n\n" + ex.ErrorCode.ToString("X") + "\n";
                QTUtils qtu = new QTUtils();
                errMsg += "QT Error code : " + qtu.QTErrorFromErrorCode(ex.ErrorCode).ToString();
                trace(errMsg);
            }
            catch (Exception ex)
            {
                // catch any exception
                errMsg = "Unable To Load the Video , Please Check if it is QuickTime Playable Video \n\n" + ex.ToString(); 
                trace(errMsg);
            }

            if (errMsg != "")
            {
                string msg = "Unable to create movie:\n\n";
                msg += errMsg;
                trace(msg);
            }

        }

        public void ExtractImage(int x, int y, string MoviePathName, string targetPathName, string overlayPic, int alpha, int totalSlice, int sliceIndex, disPlayDelegate trace, disPlayProgess showProgress)
        {
            string errMsg = "";
            ImageOverLay overlayOb = new ImageOverLay();
            ImageIngestion.ImageIngestion imageIngestOb = new ImageIngestion.ImageIngestion();

            //Initialize the Control with Resize parameter + the offset adjustment for the quickTime.
            //initialize(MoviePathName);
            //Resize the Controler 
            axQTControl1.Sizing = QTSizingModeEnum.qtControlFitsMovie;

            try
            {
                QTMovie theMovie = axQTControl1.Movie;
                Image overLay = Image.FromFile(overlayPic);

                //Get the proper rate of capturing movie frame
                float tRate = (float)600 / theMovie.StaticFrameRate;
                string digitNumber = theMovie.EndTime.ToString();
                int number = digitNumber.Length;
                string digitN;
                string suffix;
                int nu;
                int endTime = theMovie.EndTime;

                for (float i = 0; i < endTime; i = i + tRate)
                {
                    //Get the frame at specific time 
                    theMovie.CopyFrame(i);

                    Image oImage = Clipboard.GetImage();
                    if (oImage != null)
                    {
                        //Call overlayImage function to apply overlay image
                        //oImage = overlayOb.OverlayImage(oImage, overLay, alpha);

                        //Ingested the required Image
                        oImage = imageIngestOb.DivideImage(totalSlice, sliceIndex, oImage, x, y);

                        //Start suffix adding for file name
                        suffix = "";
                        digitN = i.ToString();
                        nu = digitN.Length;
                        //Get the suffix for naming
                        for (int j = 0; j < (number - nu); j++)
                            suffix = suffix + '0';
                        oImage.Save(targetPathName + "\\" + suffix + i + ".jpg", ImageFormat.Jpeg);
                        oImage.Dispose();
                        //Call the CallBack fucntion to update the Progress of the Extraction
                        showProgress(Convert.ToInt32(i/endTime*100));
                    }
                    Clipboard.Clear();

                }
                axQTControl1.Dispose();

            }
            catch (COMException ex)
            {
                // catch COM exceptions from QT control
                errMsg = "Unable To Load the Movie , Please Check if it is QuickTime Playable Video \n\n" + ex.ErrorCode.ToString("X") + "\n";
                QTUtils qtu = new QTUtils();
                errMsg += "QT Error code : " + qtu.QTErrorFromErrorCode(ex.ErrorCode).ToString();
                trace(errMsg);
            }
            catch (Exception ex)
            {
                // catch any exception
                errMsg = "Unable To Load the Movie , Please Check if it is QuickTime Playable Video \n\n" + ex.ToString();
                trace(errMsg);
            }

            if (errMsg != "")
            {
                string msg = "Unable to create movie:\n\n";
                msg += errMsg;
                trace(msg);
            }

        }


        /// <summary>
        /// Extract frames from the given Video Path, will Take .avi and .mov 
        /// </summary>
        /// <param name="MoviePathName">Movie Path </param>
        /// <param name="targetPathName">Saving Path</param>
        /// <param name="giveTotalFrame">Call Back Function to give the total Frame will be extracted</param>
        /// <param name="trace">Call Back Error Tracing </param>
        public void ExtractImage(bool Ribbons, string MoviePathName, string targetPathName, string audioPathName, updateFrame giveTotalFrame, disPlayDelegate trace)
        {
            axQTControl1.URL = MoviePathName;
            QTMovie theMovie = axQTControl1.Movie;
            QTQuickTime qt = axQTControl1.QuickTime;
            if (qt.Exporters.Count == 0) qt.Exporters.Add();
            QTExporter ex = qt.Exporters[1];
            int totalFrame;
            bool MitsuDoubleFrame = false;

            if (theMovie.StaticFrameRate < 28)
            {
                MessageBox.Show("FrameRate need to be higher than 29.97");
                giveTotalFrame(-1, MitsuDoubleFrame);
                return;
            }

            FileInfo fInfo = new FileInfo(MoviePathName);

            if (theMovie.StaticFrameRate == 30 || theMovie.StaticFrameRate == 60 || fInfo.Extension.ToLower() == ".avi")
                totalFrame = (int)(theMovie.EndTime * theMovie.StaticFrameRate / 600);
            else
            {
                totalFrame = (int)(theMovie.EndTime / 100);
                if (theMovie.StaticFrameRate > 30)
                    totalFrame = totalFrame * 2;
            }


            ex.TypeName = "Image Sequence";
            ex.SetDataSource(axQTControl1.Movie);

            //Load the XML Setting
            CFObject cf = new CFObject();
            //cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Jul 30 11:16:42 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAAAAAAAAABhmdHlwAAAAAQAAAAAAAAAASlBFRwAA\n\tABUiICI/AAAAAQAAAAAAAAAAAQ==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";

            if (Ribbons)
            {
                totalFrame = (int)((((double)totalFrame) / theMovie.StaticFrameRate) * 30);

                cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Oct 15 12:11:23 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAB4AAAAAABhmdHlwAAAAAQAAAAAAAAAAQk1QZgAA\n\tABUiICI/AAAAAQAAAAAAAAAAAA==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
            }
            else
            {
                cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Fri Oct 12 14:20:03 2007\n</string>\n\t<key>Format</key>\n\t<string>grex</string>\n\t<key>Name</key>\n\t<string>Image Sequence</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAAAbXNlYW4AAAABAAAAAwAAAAAAAAAsdGltZQAAAAEAAAABAAAA\n\tAAAAABhmcHMgAAAAAQAAAAAAAAAAAAAAAAAAABhmdHlwAAAAAQAAAAAAAAAAQk1QZgAA\n\tABUiICI/AAAAAQAAAAAAAAAAAQ==\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
                if (theMovie.StaticFrameRate < 31)
                    MitsuDoubleFrame = true;
            }
            ex.Settings = cf;

            giveTotalFrame(totalFrame , MitsuDoubleFrame);

            //Export Movie

            ex.DestinationFileName = targetPathName + "\\"+"Temp";
            ex.ShowProgressDialog = true;
            try
            {
                //Start Exporting 
                ex.BeginExport();
            }
            catch (Exception err)
            {
                // catch any exception
                string errMsg = "Unable To Extract the Movie , Please Check if it is QuickTime Playable Video \n\n" + err.ToString();
                trace(errMsg);
            }

            finally
            {
                //Check if the Frame had been extracted
                if (Directory.Exists(targetPathName))
                {
                    DirectoryInfo dir = new DirectoryInfo(targetPathName);
                    FileInfo[] files = dir.GetFiles();

                    //if the the Extraction was incompletely due to Error, call back to return the -1
                    if (files.Length < (totalFrame - 20))
                    {
                        MessageBox.Show("user Cancel or Error");
                        giveTotalFrame(-1, false);
                    }
                }
                else
                {
                    giveTotalFrame(-1, false); //if the User terminate the Video Extraction before it finish , return -1 to the main application
                }
            }

            if (qt.Exporters.Count == 1) qt.Exporters.Add();
            QTExporter ex2 = qt.Exporters[2];

            ex2.TypeName = "Wave";
            ex2.SetDataSource(axQTControl1.Movie);
            cf.XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Date</key>\n\t<string>Mon Sep 10 11:37:13 2007\n</string>\n\t<key>Format</key>\n\t<string>WAVE</string>\n\t<key>Name</key>\n\t<string>Wave</string>\n\t<key>SettingsData</key>\n\t<data>\n\tAAAAAAAAAAAAAAAAAAABbXNlYW4AAAABAAAAAQAAAAAAAAFZc291bgAAAAEAAAAGAAAA\n\tAAAAAM1hdWRpAAAAAQAAAAUAAAAAAAAAPG9zYmQAAAABAAAAAAAAAABA53AAAAAAAGxw\n\tY20AAAAMAAAABAAAAAEAAAAEAAAAAgAAABAAAAAAAAAANGNsYXkAAAABAAAAAAAAAAAA\n\tZQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVyZWNvAAAAAQAAAAAAAAAA\n\tAAAAABhxbHR5AAAAAQAAAAAAAAAAAAAAQAAAABx2ZXJzAAAAAQAAAAAAAAAAAAMAFQAB\n\tAAAAAAAYc3NjdAAAAAEAAAAAAAAAAHNvd3QAAAAYc3NydAAAAAEAAAAAAAAAALuAAAAA\n\tAAAWc3NzcwAAAAEAAAAAAAAAAAAQAAAAFnNzY2MAAAABAAAAAAAAAAAAAgAAABx2ZXJz\n\tAAAAAQAAAAAAAAAAAAMAFAABAAA=\n\t</data>\n\t<key>Type</key>\n\t<string>Movie</string>\n</dict>\n</plist>\n";
            ex2.Settings = cf;
            ex2.DestinationFileName = audioPathName;
            ex2.ShowProgressDialog = false;

            try
            {
                //Start Exporting 
                ex2.BeginExport();
            }
            catch (Exception err)
            {
                // catch any exception
                string errMsg = "Unable To Extract the Audio , Please Check if thereis a Audio in the Movie \n\n" + err.ToString();
                trace(errMsg);
            }
        }


        public void ImageSetting(string MoviePathName, string targetPathName)
        {
            //initialize(MoviePathName);

            QTQuickTime qt = axQTControl1.QuickTime;

            if (qt.Exporters.Count == 0)
                qt.Exporters.Add();
            QTExporter ex = qt.Exporters[1];

            ex.TypeName = "Image Sequence";
            ex.SetDataSource(axQTControl1.Movie);

            string exporterSettingsPath = Application.StartupPath + "\\Settings";
            string exporterSettingsFileName = exporterSettingsPath + "\\" + ex.TypeName + ".plist";

            StreamReader sr = new StreamReader(exporterSettingsFileName);
            string test = sr.ReadToEnd();

            //Configure Exporter
            ex.ShowSettingsDialog();

            //Export Movie
            ex.DestinationFileName = targetPathName;
            ex.ShowProgressDialog = true;
            ex.BeginExport();

            //Save Exporter Settting
            if (!Directory.Exists(exporterSettingsPath))
                Directory.CreateDirectory(exporterSettingsPath);

            StreamWriter sw = File.CreateText(exporterSettingsFileName);
            sw.Write(ex.Settings.XML);
            sw.Close();
        }

        public void VideoInitialize()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VideoIngestion));
            this.axQTControl1 = new AxQTOControlLib.AxQTControl();
            ((System.ComponentModel.ISupportInitialize)(this.axQTControl1)).BeginInit();
            this.SuspendLayout();
            // 
            // axQTControl1
            // 
            this.axQTControl1.Enabled = true;
            this.axQTControl1.Location = new System.Drawing.Point(43, 39);
            this.axQTControl1.Name = "axQTControl1";
            this.axQTControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axQTControl1.OcxState")));
            this.axQTControl1.Size = new System.Drawing.Size(192, 192);
            this.axQTControl1.TabIndex = 0;
            // 
            // VideoIngestion
            // 
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.axQTControl1);
            this.Name = "VideoIngestion";
            ((System.ComponentModel.ISupportInitialize)(this.axQTControl1)).EndInit();
            this.ResumeLayout(false);

        }

    }
}
